package com.tomato.base.dynamic.db.router;

import com.tomato.base.dynamic.db.annotation.DynamicDataSourceAnnotation;
import com.tomato.base.dynamic.db.enums.StrategyTypeEnum;
import com.tomato.base.dynamic.db.spring.boot.autoconfigure.properties.DynamicDataSourceProperties;
import com.tomato.base.dynamic.db.strategy.BaseStrategy;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;

/**
 * 多数据源处理
 *
 * @author lizhifu
 * @date 2021/9/8
 */
@Aspect
@Order(1) // 保障优先执行
public class DynamicDataSourceAspect {
    private Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);

    private DynamicDataSourceProperties dynamicDataSourceProperties;

    public DynamicDataSourceAspect(DynamicDataSourceProperties dynamicDataSourceProperties){
        this.dynamicDataSourceProperties = dynamicDataSourceProperties;
    }
    @Pointcut(value = "@annotation(com.tomato.base.dynamic.db.annotation.DynamicDataSourceAnnotation)")
    public void aopPointcut(){}

    @Around(value= "aopPointcut() && @annotation(dynamicDataSourceAnnotation)")
    public Object doAround(ProceedingJoinPoint jp, DynamicDataSourceAnnotation dynamicDataSourceAnnotation) throws Throwable {
        String dbKeyAttr = "";
        String specialDataSource = dynamicDataSourceAnnotation.specialDataSource();
        String strategy = dynamicDataSourceAnnotation.strategy();


        if(StringUtils.isNotBlank(specialDataSource)){
            dbKeyAttr = specialDataSource;
        }else {
            String dbKey = dynamicDataSourceAnnotation.key();
            // 路由属性
            dbKeyAttr = getAttrValue(dbKey, jp.getArgs());
        }

        if (StringUtils.isBlank(dbKeyAttr)) {
            throw new RuntimeException("路由数据不能为空");
        }
        StrategyTypeEnum.buildBaseStrategy(strategy, dynamicDataSourceProperties).dynamic(dbKeyAttr);
        // 执行
        try {
            return jp.proceed();
        } finally {
            StrategyTypeEnum.buildBaseStrategy(strategy, dynamicDataSourceProperties).clear();
        }
    }
    public String getAttrValue(String attr, Object[] args) {
        if (1 == args.length) {
            Object arg = args[0];
            if (arg instanceof String) {
                return arg.toString();
            }
        }

        String filedValue = null;
        for (Object arg : args) {
            try {
                if (StringUtils.isNotBlank(filedValue)) {
                    break;
                }
                filedValue = BeanUtils.getProperty(arg, attr);
            } catch (Exception e) {
                logger.error("获取路由属性值失败 attr：{}", attr, e);
            }
        }
        return filedValue;
    }
}
